package o2o.delivery.service;

import com.alibaba.fastjson.JSON;
import com.jinyou.utils.common.Geohash;
import com.jinyou.utils.common.ObjectUtils;
import lombok.extern.slf4j.Slf4j;
import o2o.cache.agent.CityAgentMemory;
import o2o.cache.agent.ShopAgentRelationMemory;
import o2o.cache.order.OrderInfoMemory;
import o2o.cache.postman.CityPostmanMemory;
import o2o.cache.postman.PostmanPositionMemory;
import o2o.cache.shop.ShopMemory;
import o2o.cache.sys.SysCustomerCache;
import o2o.config.dao.UserDaoSql;
import o2o.dao.PO.PojoTables;
import o2o.dao.PO.agent.CityAgent;
import o2o.dao.PO.order.ORDER_STATUS;
import o2o.dao.PO.order.OrderInfo;
import o2o.postman.model.CityPostman;
import o2o.dao.PO.postman.PostmanPositionInfo;
import o2o.company.model.ShopInfo;
import o2o.dao.VO.agent.CityAgentVO;
import o2o.dao.VO.order.OtherOrderInfoVO;
import o2o.delivery.model.to.ThridPlateDeliveryOrderTO;
import o2o.delivery.model.vo.DeliveryOrderVO;
import o2o.delivery.utils.DeliveryHttpClientUtil;
import o2o.service.order.other.OtherOrderService;
import o2o.web.actions.agent.CityAgentMan;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Jahnke【1029777564@qq.com】
 * @ClassName DeliveryOrderService
 * @Description:
 * @date 2021/1/28 16:50
 * @Version 1.0
 */
@Service
@Slf4j
public class DeliveryOrderService {

    @Autowired
    private OtherOrderService otherOrderService;

    public DeliveryOrderVO addDeliveryOrder(String key, ThridPlateDeliveryOrderTO to) throws Exception {
        log.info("数据==>{}",JSON.toJSONString(to));
        // 获取订单号
        String orderNo = getOrderNo(to.getSource(), to.getOriginOrderNo());
        OrderInfo orderExist = OrderInfoMemory.getInstance().getOrderInfo(getOrderNo(to.getSource(), to.getOriginOrderNo()));
        if (orderExist != null && orderExist.getOrderStatus() != ORDER_STATUS.PAYED_CANCEL) {
            throw new Exception("订单已经存在，无法重复添加");
        }
        if (orderExist != null && orderExist.getOrderStatus() == ORDER_STATUS.PAYED_CANCEL) {
            // 删除之前的订单，本次重新添加
            String sql = "delete from " + PojoTables.OrderInfo + " where orderNo='" + (getOrderNo(to.getSource(), to.getOriginOrderNo())) + "'";
            UserDaoSql.getInstance().executeBySql(sql);
            log.info("删除之前的订单，本次重新添加");
        }
        // 配送订单新增
        OtherOrderInfoVO orderInfo = to.convertTOInfo();
        String defaultKey = SysCustomerCache.getInstance().getDefaultKey();
        if (StringUtils.isNotEmpty(defaultKey) && defaultKey.equals("o2o-etao")) {
            orderInfo.setOrderStatus(ORDER_STATUS.PAYED);
        }
        orderInfo.setOrderNo(orderNo);
        orderInfo.setDeliveryPlateOrderNo(getOrderNo(to.getSource(), to.getPlateOrderNo()));

        // 下发配送单新增字段
        orderInfo.setOrderDeliveryTime(to.getOrderDeliveryTime());
        orderInfo.setSorts(to.getSorts());
        orderInfo.setGoodsList(to.getGoodsList());
        //根据订单绑定的ShopId查询门店
        ShopInfo shopInfo = ShopMemory.getInstance().getShopById(to.getShopId());
        if (shopInfo != null) {
            if (StringUtils.isEmpty(to.getStartName())) {
                to.setStartName(shopInfo.getShopName());
            }
            orderInfo.setFromUser(to.getStartName()).setFromPhone(shopInfo.getTelephone());
            orderInfo.setFromCity(shopInfo.getCity());
            if (Geohash.isChinaLocal(to.getStartLat(), to.getEndLng())) {
                orderInfo.setFromLng(shopInfo.getLng()).setFromLat(shopInfo.getLat());
            }
        }

        // 计算agentId
        CityAgentVO cityAgentVO = CityAgentMan.getCityAgent(null, orderInfo.getFromLat(), orderInfo.getFromLng());
        if (cityAgentVO == null) {
            cityAgentVO = CityAgentMan.getCityAgent(null, orderInfo.getToLat(), orderInfo.getToLng());
        }
        if (cityAgentVO == null && shopInfo != null) {  // 根据店铺设置
            Long agentByShopId = ShopAgentRelationMemory.getInstance().getAgentByShopId(shopInfo.getId());
            if (agentByShopId != null) {
                CityAgent byId = CityAgentMemory.getInstance().getById(agentByShopId);
                orderInfo.setAgentId(byId != null ? byId.getId() : null);
            }
        }
        if (cityAgentVO != null) {
            orderInfo.setAgentId(cityAgentVO.getId());
        }

        // 附加店铺信息
        orderInfo.setFromLat(to.getStartLat()).setFromLng(to.getStartLng()).setFromAddress(to.getStartAddr());

        try {
            otherOrderService.insertIntoPoatuiOrder(orderInfo, key, System.currentTimeMillis(), shopInfo.getId());
        } catch (SQLException e) {
            log.info("保存错误，原因==>{}",e.getMessage());
            throw new Exception("保存错误，请联系管理！");
        }

        DeliveryOrderVO deliveryOrderInfo = this.getDeliveryOrderInfo(to.getSource(), to.getOriginOrderNo(), null);
        return deliveryOrderInfo;
    }

    public DeliveryOrderVO getDeliveryOrderInfo(String source, String originOrderNo, String plateOrderNo) throws Exception {
        OrderInfo orderInfo = this.getOrderInfo(source, originOrderNo, plateOrderNo);
        if (orderInfo == null) {
            System.out.println("source:" + source + ";originOrderNo:" + originOrderNo + ";plateOrderNo:" + plateOrderNo);
            throw new Exception("未查询到有效的订单信息！");
        }
        DeliveryOrderVO deliveryOrderVO = DeliveryOrderVO.convertFromInfo(source, originOrderNo, orderInfo);
        deliveryOrderVO.setOrderNo(orderInfo.getOrderNo())
                .setPlateOrderNo(StringUtils.isEmpty(plateOrderNo) ?
                        (StringUtils.isNotEmpty(orderInfo.getDeliveryPlateOrderNo()) && orderInfo.getDeliveryPlateOrderNo().contains("_") ? orderInfo.getDeliveryPlateOrderNo().substring(0, orderInfo.getDeliveryPlateOrderNo().indexOf("_")) : orderInfo.getDeliveryPlateOrderNo())
                        : plateOrderNo);

        // 查询骑手位置
        if (StringUtils.isNotEmpty(orderInfo.getPostManUsername())) {
            CityPostman postman = CityPostmanMemory.getInstance().getPostman(orderInfo.getPostManUsername());
            if (postman != null) {
                PostmanPositionInfo postmanPositionInfo = PostmanPositionMemory.getInstance().get(postman.getId());
                if (postmanPositionInfo != null) {
                    deliveryOrderVO.setDeliveryUserLat(postmanPositionInfo.getLat()).setDeliveryUserLng(postmanPositionInfo.getLng());
                }
            }
        }

        return deliveryOrderVO;
    }

    public void cancelOrder(String source, String originOrderNo, String plateOrderNo, String cancelReason) throws Exception {
        OrderInfo orderInfo = this.getOrderInfo(source, originOrderNo, plateOrderNo);
        if (orderInfo == null) {
            throw new Exception("未查询到有效的订单信息！");
        }
        if (orderInfo.getOrderStatus() == ORDER_STATUS.OVER) {
            throw new Exception("订单已完成，无法取消！");
        }
        String sql = "update " + PojoTables.OrderInfo + " set orderStatus=" + ORDER_STATUS.PAYED_CANCEL + ",cancelReason='" + cancelReason + "' where orderNo='" + (orderInfo.getOrderNo()) + "'";
        try {
            UserDaoSql.getInstance().executeBySql(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        OrderInfoMemory.getInstance().modifyStatus(orderInfo.getOrderNo());

        // 通知回调
        this.sendNotify(source, originOrderNo);
    }

    // 订单回调通知
    public void sendNotify(String source, String originOrderNo) {
        DeliveryOrderVO vo = null;
        try {
            vo = this.getDeliveryOrderInfo(source, originOrderNo, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (vo != null && StringUtils.isNotEmpty(vo.getCallBack())) {
            log.info("订单["+originOrderNo+"_"+source+"]回调地址：" + vo.getCallBack());
            String s = DeliveryHttpClientUtil.sendPost(vo.getCallBack(), JSON.toJSONString(vo));
            log.info("配送单["+originOrderNo+"_"+source+"]回调结果：" + s);
        }
    }

    private OrderInfo getOrderInfo(String source, String originOrderNo, String plateOrderNo) {
        OrderInfo orderInfo = null;
        if (StringUtils.isNotEmpty(originOrderNo)) {
            orderInfo = OrderInfoMemory.getInstance().getOrderInfo(getOrderNo(source, originOrderNo));
        } else if (StringUtils.isNotEmpty(plateOrderNo)) {
            String sql = "select * from " + PojoTables.OrderInfo + " where deliveryPlateOrderNo='" + getOrderNo(source, plateOrderNo) + "' order by id desc";
            try {
                orderInfo = (OrderInfo) UserDaoSql.getInstance().getObject(OrderInfo.class, sql);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return orderInfo;
    }

    private static String getOrderNo(String source, String originOrderNo) {
        return originOrderNo + "_" + source;
    }

    private static Map<String, String> obj2Map(Object obj) {

        Map<String, String> map = new HashMap<String, String>();
        // System.out.println(obj.getClass());
        // 获取f对象对应类中的所有属性域
        Field[] fields = obj.getClass().getDeclaredFields();
        for (int i = 0, len = fields.length; i < len; i++) {
            String varName = fields[i].getName();
            varName = varName.toLowerCase();//将key置为小写，默认为对象的属性
            try {
                // 获取原来的访问控制权限
                boolean accessFlag = fields[i].isAccessible();
                // 修改访问控制权限
                fields[i].setAccessible(true);
                // 获取在对象f中属性fields[i]对应的对象中的变量
                Object o = fields[i].get(obj);
                if (o != null)
                    map.put(varName, o.toString());
                // System.out.println("传入的对象中包含一个如下的变量：" + varName + " = " + o);
                // 恢复访问控制权限
                fields[i].setAccessible(accessFlag);
            } catch (IllegalArgumentException ex) {
                ex.printStackTrace();
            } catch (IllegalAccessException ex) {
                ex.printStackTrace();
            }
        }
        return map;
    }

    public static void main(String[] args) {
        String str = "{\n" +
                "        \"deliveryUserPhone\": \"17888888888\",\n" +
                "        \"orderNo\": \"835775_mt\",\n" +
                "        \"distance\": 2.41,\n" +
                "        \"orderCreateTime\": \"2021-02-01 16:36:23\",\n" +
                "        \"callBack\": \"http://saas.myt.zrk.com.gaibang.shop:9080/delivery/receive/?channel=kaopu\",\n" +
                "        \"source\": \"mt\",\n" +
                "        \"orderAcceptTime\": \"2021-02-01 16:36:23\",\n" +
                "        \"orderCancelTime\": \"\",\n" +
                "        \"originOrderNo\": \"835775\",\n" +
                "        \"errorReason\": \"\",\n" +
                "        \"deliveryUserLat\": 36.69316590309808,\n" +
                "        \"deliveryUser\": \"小雨\",\n" +
                "        \"orderFinishTime\": \"\",\n" +
                "        \"state\": \"wait_fetch\",\n" +
                "        \"cancelReason\": \"\",\n" +
                "        \"deliverMoney\": 0,\n" +
                "        \"deliveryUserLng\": 117.10892359570528,\n" +
                "        \"orderFetchTime\": \"\"\n" +
                "    }";
        DeliveryOrderVO vo = JSON.parseObject(str, DeliveryOrderVO.class);

        // Map<String, String> map = obj2Map(vo);
        // map.put("channel", "kaopu");
        Map<String, Object> map = ObjectUtils.beanToMap(vo);
        // 通知
        System.out.println("订单回调：" + vo.getCallBack());
        String s = DeliveryHttpClientUtil.sendPost(vo.getCallBack(), JSON.toJSONString(map));
        System.out.println("配送单回调：" + s);
    }
}
